package cn.damong.utils.http;

import java.io.IOException;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;

/**
 * 描述：http请求工具 来源：https://gitee.com/895873144/codes/fe7l9ujrmyx4c08idvagw26
 *
 * @author 张烨腾
 * @version 2018-09-13 改订
 */
public class HttpUtil {

    private static String accept = "application/json;charset=UTF-8";

    /**
     * 不带参数的get请求
     * 
     * @param url
     *            地址
     * @return 响应体内容
     * @throws IOException
     */
    public static String get(String url) throws IOException {
        Request request = Request.Get(parseGet(url, null));
        addHeader(request);
        return request(request, null, null);
    }

    /**
     * 带参数的get请求
     * 
     * @param url
     *            地址
     * @param param
     *            参数
     * @return 响应体内容
     * @throws IOException
     */
    public static String get(String url, Map<String, String> param) throws IOException {
        Request request = Request.Get(parseGet(url, param));
        addHeader(request);
        return request(request, null, null);
    }

    /**
     * 带身份校验的get请求
     * 
     * @param url
     *            地址
     * @param param
     *            参数
     * @param userName
     *            用户名
     * @param password
     *            密码
     * @return 响应体内容
     * @throws IOException
     */
    public static String get(String url, Map<String, String> param, String userName, String password)
            throws IOException {
        Request request = Request.Get(parseGet(url, param));
        addHeader(request);
        return request(request, userName, password);
    }

    /**
     * 将get请求的参数解析成字符串的形式
     * 
     * @param url
     *            地址
     * @param param
     *            参数
     * @return 解析成字符串形式的get请求
     */
    private static String parseGet(String url, Map<String, String> param) {
        StringBuilder p = new StringBuilder();
        p.append(url);
        if (param != null && param.size() != 0) {
            p.append("?");
            for (Map.Entry<String, String> entry : param.entrySet()) {
                p.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        String s = p.toString();
        if (s.endsWith("&")) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }

    /**
     * 提交form表单的post请求
     * 
     * @param url
     *            地址
     * @param param
     *            form表单参数
     * @return 响应体内容
     * @throws IOException
     */
    public static String postForm(String url, Map<String, String> param) throws IOException {
        return postForm(url, param, null, null);
    }

    /**
     * 带身份校验的form表单的post请求
     * 
     * @param url
     *            地址
     * @param param
     *            form表单参数
     * @param userName
     *            用户名
     * @param password
     *            密码
     * @return 返回响应体内容
     * @throws IOException
     */
    public static String postForm(String url, Map<String, String> param, String userName, String password)
            throws IOException {
        Form form = Form.form();
        if (param != null) {
            param.forEach(form::add);
        }
        Request request = Request.Post(url).bodyForm(form.build());
        addHeader(request);
        return request(request, userName, password);
    }

    /**
     * Post请求
     * 
     * @param url
     *            请求地址
     * @param content
     *            请求内容
     * @param contentType
     *            请求内容类型，例：ContentType.APPLICATION_XML
     * @return 返回响应体内容
     * @throws IOException
     */
    public static String postString(String url, String content, ContentType contentType) throws IOException {
        return postString(url, content, contentType, null, null);
    }

    /**
     * Post请求
     * 
     * @param url
     *            请求地址
     * @param content
     *            请求内容
     * @param contentType
     *            请求内容类型，例：ContentType.APPLICATION_XML
     * @param userName
     *            用户名
     * @param password
     *            密码
     * @return 返回响应体内容
     * @throws IOException
     */
    public static String postString(String url, String content, ContentType contentType, String userName,
            String password) throws IOException {
        Request request = Request.Post(url).bodyString(content, contentType);
        addHeader(request);
        return request(request, userName, password);
    }

    private static void addHeader(Request request) {
        if (StringUtils.isNotBlank(accept)) {
            request.addHeader("Accept", accept);
        }
    }

    /**
     * 执行请求
     * 
     * @param request
     *            请求
     * @param userName
     *            用户名
     * @param password
     *            密码
     * @return 返回响应体内容
     * @throws IOException
     */
    private static String request(Request request, String userName, String password) throws IOException {
        Executor executor = Executor.newInstance();
        if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) {
            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(userName, password);
            executor.auth(AuthScope.ANY, creds);
        }
        return executor.execute(request).returnContent().asString();
    }
}
